﻿using System.Collections.Concurrent;
using System.Collections.Generic;

namespace Multiprocessing.Core.Mathematics.Matrices
{
    public class SparseMatrix : BaseMatrix
    {
        #region Fields

        private IDictionary<MatrixCoordinate, double> _underlaying;

        #endregion

        #region Constructors

        public SparseMatrix(int rowCount, int columnCount) 
            : base(rowCount, columnCount)
        {

        }

        #endregion

        protected override void CreateUnderlaying(int row, int column)
        {
            _underlaying = new ConcurrentDictionary<MatrixCoordinate, double>();
        }

        protected override IMatrix CloneMatrix()
        {
            IMatrix destionation = new SparseMatrix(this.RowCount, this.ColumnCount);
            CloneMatrix(this, destionation);
            return destionation;
        }

        public override double GetElement(int row, int column)
        {
            MatrixCoordinate key = MatrixCoordinate.Create(row, column);
            double value = 0.0;
            _underlaying.TryGetValue(key, out value);
            return value;
        }

        public override void SetElement(int row, int column, double value)
        {
            MatrixCoordinate key = MatrixCoordinate.Create(row, column);
            if (_underlaying.ContainsKey(key))
                _underlaying[key] = value;
            else
                _underlaying.Add(key, value);
        }

        public override IMatrix Add(IMatrix matrix)
        {
            IMatrix result = new SparseMatrix(RowCount, ColumnCount);
            Add(this, matrix, result);
            return result;
        }

        public override IMatrix Substract(IMatrix matrix)
        {
            IMatrix result = new SparseMatrix(RowCount, ColumnCount);
            Substract(this, matrix, result);
            return result;
        }

        public override IMatrix Multiply(IMatrix matrix)
        {
            IMatrix result = new SparseMatrix(this.RowCount, matrix.ColumnCount);
            Multiply(this, matrix, result);
            return result;
        }

        public override IMatrix Multiply(double value)
        {
            IMatrix result = new SparseMatrix(this.RowCount, this.ColumnCount);
            Multiply(this, value, result);
            return result;
        }

        public override IMatrix Divide(double value)
        {
            IMatrix result = new SparseMatrix(this.RowCount, this.ColumnCount);
            Divide(this, value, result);
            return result;
        }
    }
}
